package algortims;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

import org.apache.commons.lang3.StringUtils;

import entility.StringNormalize;

public class EditDistance extends Thread {

	private String FileName;
	private StringNormalize normalize;
	private List<String> FileContent;
	private Set<String> wordIndexed;
	public volatile boolean running;

	public EditDistance() {
		running = false;
	}

	public EditDistance(String head, List<String> FileContent) {

		this.FileContent = FileContent;
		this.setFileName(head);
		this.normalize = new StringNormalize();
	}

	public void Index() {

		Set<String> words = new TreeSet<String>();
		for (String line : FileContent) {
			try {
				String l = normalize.normalize(line);
				if (l != null) {
					String lines[] = l.split(" ");
					for (String word : lines) {
						words.add(word.trim());
					}
				}

			} catch (Exception e) {
				System.out.println("Erro");
			}

		}

		this.setWordIndexed(words);

	}

	public List<String> Levenshtein(String s, Set<String> textos,
			float threshold) {
		List<String> aux = new LinkedList<String>();
		float size2 = s.length();

		for (String umTexto : textos) {
			float size1 = umTexto.length();
			float porcentagem = 0;

			if (size1 > size2)
				porcentagem = size1 / size2;
			else
				porcentagem = size2 / size1;

			// palavras com menos do que 50% de diferenca nos tamanhos
			if (porcentagem < 1.5) {
				float r = StringUtils.getLevenshteinDistance(s, umTexto);
				// X% de diferença ou menos
				if (((r / size1) >= 0) && ((r / size1) < threshold))
					aux.add(umTexto);
			}
		}

		return aux;
	}

	/**
	 * Metodo que dada uma palavra é possivel saber qual palavra é a mais
	 * similar. Neste método o grau de diferença é fixado em 20%
	 * 
	 * @param s
	 *            a palavra a ser analisada
	 * @param textos
	 *            é o conjunto de palavras onde se alemja buscar a mais similar
	 * @return a palavra mais similar ou "" - VAZIO
	 */
	public String Levenshtein(String s, Set<String> textos) {
		String aux = "";
		float diff = 0;

		float size2 = s.length();

		for (String umTexto : textos) {
			// System.err.println(s +"  &&  " + umTexto);
			float size1 = umTexto.length();
			float porcentagem = 0;

			if (size1 > size2)
				porcentagem = size1 / size2;
			else
				porcentagem = size2 / size1;

			// palavras com menos do que 50% de diferenca nos tamanhos
			if (porcentagem < 1.5) {
				float r = StringUtils.getLevenshteinDistance(s, umTexto);
				// X% de diferença ou menos
				if (((r / size1) >= 0) && ((r / size1) <= 0.43))
					if (diff == 0) {
						diff = r / size1;
						aux = umTexto;
					} else if ((r / size1) < diff) {
						aux = umTexto;
						diff = r / size1;
					}

			}
		}

		return aux;
	}

	public void getDistance() {

		Map<String, String> dictionary = new HashMap<String, String>();

		List<String> words = new ArrayList<String>(wordIndexed);

		for (String word : words) {
			wordIndexed.remove(word);
			String x = Levenshtein(word, wordIndexed);
			if (x != null && !x.equals("")) {
				dictionary.put(word, x);
			}
			wordIndexed.add(word);
		}

		// System.out.println(this.FileName);

		// this.normalize.writeFile("Dictionary.txt", dictionary.toString());

	}

	public void run() {
		running = true;
		this.Index();
		this.getDistance();
		running = false;

	}

	public String getFileName() {
		return FileName;
	}

	public void setFileName(String fileName) {
		FileName = fileName;
	}

	public Set<String> getWordIndexed() {
		return wordIndexed;
	}

	public void setWordIndexed(Set<String> wordIndexed) {
		this.wordIndexed = wordIndexed;
	}

}